<template>
  <div class="element-toolbar">
    <Tabs 
      :tabs="tabs" 
      v-model:value="activeTab" 
      :tabsStyle="{ marginBottom: '8px' }" 
      :tabStyle="{
        width: '30%',
        margin: '0 10%',
      }" 
    />

    <div class="content">
      <div class="style" v-if="activeTab === 'style'">
        <template v-if="textPropsEnable">
          <ButtonGroup class="row">
            <CheckboxButton 
              style="flex: 1;"
              :checked="richTextAttrs.bold"
              @click="emitRichTextCommand('bold')"
            ><IconTextBold /></CheckboxButton>
            <CheckboxButton 
              style="flex: 1;"
              :checked="richTextAttrs.em"
              @click="emitRichTextCommand('em')"
            ><IconTextItalic /></CheckboxButton>
            <CheckboxButton 
              style="flex: 1;"
              :checked="richTextAttrs.underline"
              @click="emitRichTextCommand('underline')"
            ><IconTextUnderline /></CheckboxButton>
            <CheckboxButton 
              style="flex: 1;"
              :checked="richTextAttrs.strikethrough"
              @click="emitRichTextCommand('strikethrough')"
            ><IconStrikethrough /></CheckboxButton>
          </ButtonGroup>

          <ButtonGroup class="row">
            <Button 
              style="flex: 1;"
              @click="emitRichTextCommand('fontsize-add')"
            ><IconFontSize />+</Button>
            <Button 
              style="flex: 1;"
              @click="emitRichTextCommand('fontsize-reduce')"
            ><IconFontSize />-</Button>
          </ButtonGroup>

          <RadioGroup 
            class="row" 
            button-style="solid" 
            :value="richTextAttrs.align"
            @update:value="value => emitRichTextCommand('align', value)"
          >
            <RadioButton value="left" style="flex: 1;"><IconAlignTextLeft /></RadioButton>
            <RadioButton value="center" style="flex: 1;"><IconAlignTextCenter /></RadioButton>
            <RadioButton value="right" style="flex: 1;"><IconAlignTextRight /></RadioButton>
          </RadioGroup>
        </template>

        <div class="row-block" v-if="textColorPropsEnable">
          <div class="label">文字颜色：</div>
          <div class="colors">
            <div class="color" 
              v-for="color in colors" 
              :key="color"
              @click="updateFontColor(color)"
            >
              <div class="color-block" :style="{ backgroundColor: color }"></div>
            </div>
            <div class="color custom">
              <Popover trigger="click">
                <template #content>
                  <ColorPicker @update:modelValue="value => updateFontColor(value)" />
                </template>
                <div class="color-block"></div>
              </Popover>
            </div>
          </div>
        </div>
        <div class="row-block" v-if="fillPropsEnable">
          <div class="label">填充色：</div>
          <div class="colors">
            <div class="color" 
              v-for="color in colors" 
              :key="color"
              @click="updateFill(color)"
            >
              <div class="color-block" :style="{ backgroundColor: color }"></div>
            </div>
            <div class="color custom">
              <Popover trigger="click">
                <template #content>
                  <ColorPicker @update:modelValue="value => updateFill(value)" />
                </template>
                <div class="color-block"></div>
              </Popover>
            </div>
          </div>
        </div>

        <div class="tip" v-if="!textPropsEnable && !textColorPropsEnable && !fillPropsEnable">暂无可用属性</div>
      </div>

      <div class="common" v-if="activeTab === 'common'">
        <ButtonGroup class="row">
          <Button style="flex: 1;" @click="copyElement()"><IconCopy class="icon" /> 复制</Button>
          <Button style="flex: 1;" @click="deleteElement()"><IconDelete class="icon" /> 删除</Button>
        </ButtonGroup>
        
        <Divider :margin="20" />

        <ButtonGroup class="row">
          <Button style="flex: 1;" @click="orderElement(handleElement!, ElementOrderCommands.TOP)"><IconSendToBack class="icon" /> 置顶</Button>
          <Button style="flex: 1;" @click="orderElement(handleElement!, ElementOrderCommands.BOTTOM)"><IconBringToFrontOne class="icon" /> 置底</Button>
          <Button style="flex: 1;" @click="orderElement(handleElement!, ElementOrderCommands.UP)"><IconBringToFront class="icon" /> 上移</Button>
          <Button style="flex: 1;" @click="orderElement(handleElement!, ElementOrderCommands.DOWN)"><IconSentToBack class="icon" /> 下移</Button>
        </ButtonGroup>
        
        <Divider :margin="20" />

        <ButtonGroup class="row">
          <Button style="flex: 1;" @click="alignElementToCanvas(ElementAlignCommands.LEFT)"><IconAlignLeft class="icon" /> 左对齐</Button>
          <Button style="flex: 1;" @click="alignElementToCanvas(ElementAlignCommands.HORIZONTAL)"><IconAlignVertically class="icon" /> 水平居中</Button>
          <Button style="flex: 1;" @click="alignElementToCanvas(ElementAlignCommands.RIGHT)"><IconAlignRight class="icon" /> 右对齐</Button>
        </ButtonGroup>
        <ButtonGroup class="row">
          <Button style="flex: 1;" @click="alignElementToCanvas(ElementAlignCommands.TOP)"><IconAlignTop class="icon" /> 上对齐</Button>
          <Button style="flex: 1;" @click="alignElementToCanvas(ElementAlignCommands.VERTICAL)"><IconAlignHorizontally class="icon" /> 垂直居中</Button>
          <Button style="flex: 1;" @click="alignElementToCanvas(ElementAlignCommands.BOTTOM)"><IconAlignBottom class="icon" /> 下对齐</Button>
        </ButtonGroup>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { computed, ref } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import type { PPTElement, TableCell } from '@/types/slides'
import { ElementAlignCommands, ElementOrderCommands } from '@/types/edit'
import emitter, { EmitterEvents } from '@/utils/emitter'
import useOrderElement from '@/hooks/useOrderElement'
import useAlignElementToCanvas from '@/hooks/useAlignElementToCanvas'
import useDeleteElement from '@/hooks/useDeleteElement'
import useAddSlidesOrElements from '@/hooks/useAddSlidesOrElements'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'

import CheckboxButton from '@/components/CheckboxButton.vue'
import Tabs from '@/components/Tabs.vue'
import Divider from '@/components/Divider.vue'
import Button from '@/components/Button.vue'
import ButtonGroup from '@/components/ButtonGroup.vue'
import RadioButton from '@/components/RadioButton.vue'
import RadioGroup from '@/components/RadioGroup.vue'
import ColorPicker from '@/components/ColorPicker/index.vue'
import Popover from '@/components/Popover.vue'

interface TabItem {
  key: 'style' | 'common'
  label: string
}

const colors = ['#000000', '#ffffff', '#eeece1', '#1e497b', '#4e81bb', '#e2534d', '#9aba60', '#8165a0', '#47acc5', '#c21401', '#ff1e02', '#ffc12a', '#ffff3a', '#90cf5b', '#00af57']

const mainStore = useMainStore()
const slidesStore = useSlidesStore()
const { handleElement, handleElementId, richTextAttrs } = storeToRefs(mainStore)

const { addHistorySnapshot } = useHistorySnapshot()

const updateElement = (id: string, props: Partial<PPTElement>) => {
  slidesStore.updateElement({ id, props })
  addHistorySnapshot()
}

const tabs: TabItem[] = [
  { key: 'style', label: '样式' },
  { key: 'common', label: '布局' },
]
const activeTab = ref('common')

const textPropsEnable = computed(() => {
  if (!handleElement.value) return false
  if (handleElement.value.type === 'text') return true
  if (handleElement.value.type === 'shape' && handleElement.value.text?.content) return true

  return false
})

const textColorPropsEnable = computed(() => {
  if (!handleElement.value) return false
  if (
    handleElement.value.type === 'text' ||
    handleElement.value.type === 'table' ||
    handleElement.value.type === 'latex'
  ) return true

  if (handleElement.value.type === 'shape' && handleElement.value.text?.content) return true

  return false
})

const fillPropsEnable = computed(() => {
  if (!handleElement.value) return false
  if (
    handleElement.value.type === 'text' ||
    handleElement.value.type === 'shape' ||
    handleElement.value.type === 'chart' ||
    handleElement.value.type === 'table' ||
    handleElement.value.type === 'line' ||
    handleElement.value.type === 'audio'
  ) return true

  return false
})

const { orderElement } = useOrderElement()
const { alignElementToCanvas } = useAlignElementToCanvas()
const { addElementsFromData } = useAddSlidesOrElements()
const { deleteElement } = useDeleteElement()

const copyElement = () => {
  const element: PPTElement = JSON.parse(JSON.stringify(handleElement.value))
  addElementsFromData([element])
}

const emitRichTextCommand = (command: string, value?: string) => {
  emitter.emit(EmitterEvents.RICH_TEXT_COMMAND, { action: { command, value } })
}

const updateFontColor = (color: string) => {
  if (!handleElement.value) return
  if (handleElement.value.type === 'text' || (handleElement.value.type === 'shape' && handleElement.value.text?.content)) {
    emitter.emit(EmitterEvents.RICH_TEXT_COMMAND, { action: { command: 'color', value: color } })
  }
  if (handleElement.value.type === 'table') {
    const data: TableCell[][] = JSON.parse(JSON.stringify(handleElement.value.data))
    for (let i = 0; i < data.length; i++) {
      for (let j = 0; j < data[i].length; j++) {
        const style = data[i][j].style || {}
        data[i][j].style = { ...style, color }
      }
    }
    updateElement(handleElementId.value, { data })
  }
  if (handleElement.value.type === 'latex') {
    updateElement(handleElementId.value, { color })
  }
}

const updateFill = (color: string) => {
  if (!handleElement.value) return
  if (
    handleElement.value.type === 'text' ||
    handleElement.value.type === 'shape' ||
    handleElement.value.type === 'chart'
  ) updateElement(handleElementId.value, { fill: color })

  if (handleElement.value.type === 'table') {
    const data: TableCell[][] = JSON.parse(JSON.stringify(handleElement.value.data))
    for (let i = 0; i < data.length; i++) {
      for (let j = 0; j < data[i].length; j++) {
        const style = data[i][j].style || {}
        data[i][j].style = { ...style, backcolor: color }
      }
    }
    updateElement(handleElementId.value, { data })
  }

  if (handleElement.value.type === 'audio' || handleElement.value.type === 'line') {
    updateElement(handleElementId.value, { color })
  }
}
</script>

<style lang="scss" scoped>
.element-toolbar {
  width: 100%;
  height: 240px;
  position: absolute;
  z-index: 99;
  bottom: 0;
  left: 0;
  background-color: #fff;
  box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.1);
  display: flex;
  flex-direction: column;
  animation: slideInUp .15s;
}

@keyframes slideInUp {
  from {
    transform: translateY(100%);
  }
  to {
    transform: translateY(0);
  }
}

.content {
  padding: 10px;
  flex: 1;
  overflow: auto;
}
.row {
  width: 100%;
  display: flex;
  align-items: center;
  margin-bottom: 10px;

  .icon {
    margin-right: 3px;
  }
}
.row-block {
  margin-bottom: 10px;
  background-color: $lightGray;
  border-radius: $borderRadius;
  padding: 10px;
}
.label {
  font-size: 13px;
  margin-bottom: 20px;
  margin-left: 6px;
}
.colors {
  @include flex-grid-layout();
}
.color {
  @include flex-grid-layout-children(8, 12%);

  padding-bottom: 5px;
  display: flex;
  justify-content: center;
  align-items: center;

  .color-block {
    width: 30px;
    height: 30px;
    border-radius: 50%;
  }

  &.custom .color-block {
    background: conic-gradient(from 0deg, #ff1e02, #ffc12a, #90cf5b, #00af57, #47acc5, #4e81bb, #8165a0, #e2534d, #ff1e02);
  }
}

.tip {
  height: 100px;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 12px;
  color: #999;
}
</style>